#pragma once

#include "BaseInc.h"
#include "Array.h"
#include "Text.h"

NAMESPACE_CORE_BEGIN

const UINT_X EXCEPTION_MAX_NAME = 64;
const UINT_X EXCEPTION_MAX_WHAT = 256;

class CORE_API CException
{
public :
	CException()
	{
		m_uiNumber = 0;
		ArrayFill<char_x>(m_szName, EXCEPTION_MAX_NAME, 0);
		ArrayFill<char_x>(m_szWhat, EXCEPTION_MAX_WHAT, 0);
	}
	CException(const char_x * szWhat)
	{
		m_uiNumber = 0;
		ArrayFill<char_x>(m_szName, EXCEPTION_MAX_NAME, 0);
		TextCopy(m_szWhat, EXCEPTION_MAX_NAME, szWhat);
	}

	CException(uint_x uiNumber, const char_x * szName)
	{
		m_uiNumber = uiNumber;
		TextCopy(m_szName, EXCEPTION_MAX_NAME, szName);
		m_szWhat[0] = 0;
	}

	CException(uint_x uiNumber, const char_x * szName, const char_x * szWhat)
	{
		m_uiNumber = uiNumber;
		TextCopy(m_szName, EXCEPTION_MAX_NAME, szName);		
		TextCopy(m_szWhat, EXCEPTION_MAX_NAME, szWhat);		
	}

	uint_x GetNumber() const { return m_uiNumber;}
	const char_x * GetName() const { return m_szName;}
	char_x * GetWhat() { return m_szWhat;}
	const char_x * GetWhat() const { return m_szWhat;}
protected :
	uint_x m_uiNumber;
	char_x m_szName[EXCEPTION_MAX_NAME];
	char_x m_szWhat[EXCEPTION_MAX_WHAT];
};

enum /*SystemException*/
{
	NotSurpportException,
	IllegalArgumentException,
	IndexOutOfBoundsException,
	NullPointerException,
	IllegalOperationException,
	BadStateException,
	OutOfMemoryException,
	NotImplementException,
	EndOfStreamException,
	StreamBadStateException,
	FileNotFoundException,
	OverflowException,
};

class CORE_API CNotSupportException : public CException
{
public :
	CNotSupportException(const char_x * szWhat = PCHAR_EMPTY) 
		: CException(NotSurpportException, _T("CNotSurpportException"), szWhat) {}
};

class CORE_API CIllegalArgumentException : public CException
{
public :
	CIllegalArgumentException(const char_x * szWhat = PCHAR_EMPTY) 
		: CException(IllegalArgumentException, _T("CIllegalArgumentException"), szWhat) {}
};

class CORE_API CIndexOutOfBoundsException : public CException
{
public :
	CIndexOutOfBoundsException(const char_x * szWhat = PCHAR_EMPTY) 
		: CException(IndexOutOfBoundsException, _T("CIndexOutOfBoundsException"), szWhat) {}
};

class CORE_API CNullPointerException : public CException
{
public :
	CNullPointerException(const char_x * szWhat = PCHAR_EMPTY) 
		: CException(NullPointerException, _T("CNullPointerException"), szWhat) {}
};

class CORE_API CIllegalOperationException : public CException
{
public :
	CIllegalOperationException(const char_x * szWhat = PCHAR_EMPTY) 
		: CException(IllegalOperationException, _T("CIllegalOperationException"), szWhat) {}
};

class CORE_API CBadStateException : public CException
{
public :
	CBadStateException(const char_x * szWhat = _T("BadStateException")) 
		: CException(BadStateException, _T("BadStateException"), szWhat) {}
};

class CORE_API COutOfMemoryException : public CException
{
public :
	COutOfMemoryException(const char_x * szWhat = PCHAR_EMPTY) 
		: CException(OutOfMemoryException, _T("COutOfMemoryException"), szWhat) {}
};

class CORE_API CNotImplementException : public CException
{
public :
	CNotImplementException(const char_x * szWhat = PCHAR_EMPTY) 
		: CException(NotImplementException, _T("NotImplementException"), szWhat) {}
};

class CORE_API COverflowException : public CException
{
public :
	COverflowException(const char_x * szWhat = PCHAR_EMPTY) 
		: CException(OverflowException, _T("OverflowException"), szWhat) {}
};

template<typename PtT>
void VerifyPointer(const PtT * const & pPt)
{
	if(pPt == nullptr)
		throw CNullPointerException();
};

template<typename PtT>
void VerifyMemory(const PtT * const & pPt)
{
	if(pPt == nullptr)
		throw COutOfMemoryException();
};
inline void VerifyParamter(bool bOk)
{
	if(!bOk)
		throw CIllegalArgumentException();
};

inline void VerifyState(bool bOk)
{
	if(!bOk)
		throw CBadStateException();
}

inline void VerifyArgument(bool bOk)
{
	if(!bOk)
		throw CIllegalArgumentException();
}

class CORE_API CStreamException : public CException
{
public :
	CStreamException(uint_x uiNumber, const char_x * szName)
		: CException(uiNumber, szName) {}
	CStreamException(uint_x uiNumber, const char_x * szName, const char_x * szWhat)		
		: CException(uiNumber, szName, szWhat) {}
};

class CORE_API CEndOfStreamException : public CStreamException
{
public:
	CEndOfStreamException(const char_x * szWhat)
		: CStreamException(EndOfStreamException, _T("EndOfStreamException"), szWhat) {}
};

class CORE_API CStreamBadStateException : public CStreamException
{
public:
	CStreamBadStateException(const char_x * szWhat)
		: CStreamException(StreamBadStateException, _T("StreamBadStateException"), szWhat) {}
};

class CORE_API CFileNotFoundException : public CStreamException
{
public:
	CFileNotFoundException()
		: CStreamException(FileNotFoundException, _T("FileNotFoundException")) {}
	CFileNotFoundException(const char_x * szWhat)
		: CStreamException(FileNotFoundException, _T("FileNotFoundException"), szWhat) {}
};

NAMESPACE_CORE_END
